#include"header/token.h"
#include"header/scanner.h"
#include"header/parser.h"
#include"header/symbol.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

token lookahead = 0; 
int previewstack_size = PARSER_DEFAULT_PREVIEWSTACK_SIZE;
int previewstack_idx = -1;
token * previewstack = 0;
int matchedstack_size = PARSER_DEFAULT_PREVIEWSTACK_SIZE;
int matchedstack_idx = -1;
void ** matchedstack = 0;

//sym_table global_sym_table = NULL;


token previewstack_pop(){
    return previewstack[previewstack_idx--];
}

void previewstack_push(token tk){
    token * tmp = 0;
    if(previewstack_idx >= previewstack_size-1){
        tmp = (token *)calloc(previewstack_size+PARSER_DEFAULT_PREVIEWSTACK_SIZE,sizeof(token));
        memcpy(tmp,previewstack,previewstack_size);
        previewstack_size += PARSER_DEFAULT_PREVIEWSTACK_SIZE;
        free(previewstack);
        previewstack = tmp;
    }
    previewstack[++previewstack_idx]=tk;
}

void * matchedstack_pop(){
    return matchedstack[matchedstack_idx--];
}

void matchedstack_push(void * tk){
    void ** tmp = 0;
    if(matchedstack_idx >= matchedstack_size-1){
        tmp = (void **)calloc(matchedstack_size+PARSER_DEFAULT_PREVIEWSTACK_SIZE,sizeof(void*));
        memcpy(tmp,matchedstack,matchedstack_size);
        matchedstack_size += PARSER_DEFAULT_PREVIEWSTACK_SIZE;
        free(matchedstack);
        matchedstack = tmp;
    }
    matchedstack[++matchedstack_idx]=tk;
}

void init_previewstack(){
    previewstack = (token *)calloc(previewstack_size,sizeof(token));
    matchedstack = (void **)calloc(previewstack_size,sizeof(void *));
}

void init_parser(){
    init_previewstack();
    //global_sym_table = init_sym_table(NULL,SYMBOL_TABLE_DEFAULT_SIZE);
}

token ahead(){
    return lookahead;
}

token advance(){
    token tk = lookahead;
    if(previewstack_idx > -1){
        lookahead = previewstack_pop();
    }else{
        lookahead = token_scan();
    }
    return tk;
}

int match(int t){
    if(token_type(ahead())==t){
        matchedstack_push(ahead());
        advance();
        return 1;
    }
    else{
       log_error();
    }
    return 0;
}

void parser_error_info(char * s){
    printf("\033[1m%s\033[0m\n",s);
}

abt_declist parse_program(){
    if(token_type(ahead())==TOKEN_VOID || token_type(ahead())==TOKEN_STRUCT ||
        token_type(ahead())==TOKEN_INT){
        parse_declaration_list();
        return matchedstack_pop();
    }
    else{
        parser_error_info("the program should be made up of declaration lists");
        log_error();
        return NULL;
    }
}

void parse_declaration_list(){
    abt_dec dec = NULL;
    if(token_type(ahead())==TOKEN_VOID || token_type(ahead())==TOKEN_STRUCT ||
        token_type(ahead())==TOKEN_INT){
        parse_declaration();
        dec = matchedstack_pop();
        parse_declaration_list_();
        matchedstack_push(abt_dec_list(dec,matchedstack_pop()));
    }
    else{
        parser_error_info("syntax error detected at declaration list");
        log_error();
    }
}

void parse_declaration_list_(){
    abt_dec dec = NULL;
    if(token_type(ahead())==TOKEN_VOID || token_type(ahead())==TOKEN_STRUCT ||
        token_type(ahead())==TOKEN_INT){
        parse_declaration();
        dec = matchedstack_pop();
        parse_declaration_list_();
        matchedstack_push(abt_dec_list(dec,matchedstack_pop()));
    }
    else{
        matchedstack_push(NULL);
        return;
    } 
}

void parse_declaration(){
    token tk1 = 0;
    token tk2 = 0;
    if(token_type(ahead())==TOKEN_VOID || token_type(ahead())==TOKEN_STRUCT ||
        token_type(ahead())==TOKEN_INT){
        tk1 = advance();
        if(token_type(ahead())==TOKEN_ID){
            tk2 = advance();
            if(token_type(ahead())==TOKEN_LEFT_BRACE){
                    previewstack_push(ahead());
                    previewstack_push(tk2);
                    previewstack_push(tk1);
                    advance();
                    parse_function_declaration();
            }else{
                    previewstack_push(ahead());
                    previewstack_push(tk2);
                    previewstack_push(tk1);
                    advance();
                    parse_variable_declaration();
            }
        }else{
            parser_error_info("syntax error detected at declaration");
            log_error();
        }
    }
    else{
        parser_error_info("error detected at declaration");
        log_error();
    } 
}

void parse_variable_declaration(){
    token tk1 = 0;
    token tk2 = 0;
    int is_type=0;
    char * ssym = NULL;
    char * sym = NULL;
    abt_declist declist = NULL;
    int size = 0;
    if(token_type(ahead())==TOKEN_VOID || token_type(ahead())==TOKEN_STRUCT ||
        token_type(ahead())==TOKEN_INT){
            if(token_type(ahead())==TOKEN_STRUCT){
                is_type = 0;
            }else if(token_type(ahead())==TOKEN_INT){
                is_type = 1;
            }else{
                is_type = 2;
            }
            parse_type_specifier();
            if(token_type(ahead())==TOKEN_ID){
                tk1 = advance();
                if(token_type(ahead())==TOKEN_SEMICOLON){
                    previewstack_push(ahead());
                    previewstack_push(tk1);
                    advance();
                    if(is_type == 0){
                        ssym = matchedstack_pop();
                        declist = matchedstack_pop();
                        match(TOKEN_ID);
                        sym = token_letter(matchedstack_pop());
                        match(TOKEN_SEMICOLON);
                        matchedstack_push(abt_struct_dec(sym,ssym,declist));
                    }else if(is_type == 1){
                        match(TOKEN_ID);
                        sym = token_letter(matchedstack_pop());
                        match(TOKEN_SEMICOLON);
                        matchedstack_push(abt_int_dec(sym));
                    }else{
                        match(TOKEN_ID);
                        sym = token_letter(matchedstack_pop());
                        match(TOKEN_SEMICOLON);
                        matchedstack_push(abt_void_dec(sym));
                    }
                }else if(token_type(ahead())==TOKEN_LEFT_SBRACE){
                    previewstack_push(ahead());
                    previewstack_push(tk1);
                    advance();
                    if(is_type==0){
                        ssym = matchedstack_pop();
                        declist = matchedstack_pop();
                        match(TOKEN_ID);
                        sym = token_letter(matchedstack_pop());
                        match(TOKEN_LEFT_SBRACE);
                        match(TOKEN_NUM);
                        size = token_digit(matchedstack_pop());
                        match(TOKEN_RIGHT_SBRACE);
                        match(TOKEN_SEMICOLON);
                        matchedstack_push(abt_array_dec(sym,size,ABT_DEC_STRUCT,ssym,declist));
                    }else if(is_type == 1){
                        match(TOKEN_ID);
                        sym = token_letter(matchedstack_pop());
                        match(TOKEN_LEFT_SBRACE);
                        match(TOKEN_NUM);
                        size = token_digit(matchedstack_pop());
                        match(TOKEN_RIGHT_SBRACE);
                        match(TOKEN_SEMICOLON);
                        matchedstack_push(abt_array_dec(sym,size,ABT_DEC_INT,NULL,NULL));
                    }else{
                        match(TOKEN_ID);
                        sym = token_letter(matchedstack_pop());
                        match(TOKEN_LEFT_SBRACE);
                        match(TOKEN_NUM);
                        size = token_digit(matchedstack_pop());
                        match(TOKEN_RIGHT_SBRACE);
                        match(TOKEN_SEMICOLON);
                        matchedstack_push(abt_array_dec(sym,size,ABT_DEC_VOID,NULL,NULL));
                    }
                }else{
                    parser_error_info("syntax error detected at variable declaration");
                    log_error();
                }
            }else{
                parser_error_info("syntax error detected at variable declaration");
                log_error();
            }
    }else{
        parser_error_info("syntax error detected at variable declaration");
        log_error();
    }
}

void parse_type_specifier(){
    
    if(token_type(ahead())==TOKEN_INT){
        match(TOKEN_INT);
    }else if(token_type(ahead())==TOKEN_VOID){
        match(TOKEN_VOID);
    }else if(token_type(ahead())==TOKEN_STRUCT){
        parse_struct_specifier();
    }else{
        parser_error_info("syntax error detected at type specifier");
        log_error();
    }
}

void  parse_struct_specifier(){
    token tk1 = 0;
    token tk2 = 0;
    char * ssym = NULL;
    if(token_type(ahead())==TOKEN_STRUCT){
        tk1 = advance();
        if(token_type(ahead())==TOKEN_ID){
            tk2 = advance();
            if(token_type(ahead())==TOKEN_LEFT_CBRACE){
                previewstack_push(ahead());
                previewstack_push(tk2);
                previewstack_push(tk1);
                advance();
                match(TOKEN_STRUCT);parse_optional_identifier();
                ssym = matchedstack_pop();
                match(TOKEN_LEFT_CBRACE);
                parse_struct_declaration_list();
                match(TOKEN_RIGHT_CBRACE);
                matchedstack_pop();
                matchedstack_push(ssym);
            }else{
                previewstack_push(ahead());
                previewstack_push(tk2);
                previewstack_push(tk1);
                advance();
                match(TOKEN_STRUCT);
                match(TOKEN_ID);
                ssym = token_letter(matchedstack_pop());
                matchedstack_push(NULL);
                matchedstack_push(ssym);
            }
        }else{
            parser_error_info("syntax error detected at struct specifier");
            log_error();
        }
    }else{
        parser_error_info("syntax error detected at struct specifier");
        log_error();
    }
}

void parse_optional_identifier(){
    if(token_type(ahead())==TOKEN_ID){
        match(TOKEN_ID);
        matchedstack_push(token_letter(matchedstack_pop()));
    }else{
        parser_error_info("syntax error detected at struct identifier");
        log_error();
    }
}

void parse_struct_declaration_list(){
    abt_dec dec = NULL;
    char *sym = NULL;
    if(token_type(ahead())==TOKEN_INT){
        match(TOKEN_INT);match(TOKEN_ID);match(TOKEN_SEMICOLON);
        matchedstack_pop();
        sym = token_letter(matchedstack_pop());
        dec = abt_int_dec(sym);
        parse_struct_declaration_list_();
        matchedstack_push(abt_dec_list(dec,matchedstack_pop()));
    }
    else if(token_type(ahead())==TOKEN_VOID){
        match(TOKEN_VOID);match(TOKEN_ID);match(TOKEN_SEMICOLON);
        matchedstack_pop();
        sym = token_letter(matchedstack_pop());
        dec = abt_void_dec(sym);
        parse_struct_declaration_list_();
        matchedstack_push(abt_dec_list(dec,matchedstack_pop()));
    }else{
        parser_error_info("syntax error detected at struct declaration");
        log_error();
    }
}

void parse_struct_declaration_list_(){
    char * sym = NULL;
    if(token_type(ahead())==TOKEN_INT){
        match(TOKEN_INT);
        match(TOKEN_ID);
        sym = token_letter(matchedstack_pop());
        match(TOKEN_SEMICOLON);
        parse_struct_declaration_list_();
        matchedstack_push(abt_dec_list(abt_int_dec(sym),matchedstack_pop()));
    }else if(token_type(ahead())==TOKEN_VOID){
        match(TOKEN_VOID);
        match(TOKEN_ID);
        sym = token_letter(matchedstack_pop());
        match(TOKEN_SEMICOLON);
        parse_struct_declaration_list_();
        matchedstack_push(abt_dec_list(abt_void_dec(sym),matchedstack_pop()));

    }else{
        matchedstack_push(NULL);
        return;
    }
}

void parse_function_declaration(){
    int is_type=0;
    abt_stmt cstmt = NULL;
    char * ssym = NULL;
    char * sym = NULL;
    abt_declist declist = NULL;
    abt_declist arglist = NULL;
    int size = 0;
    if(token_type(ahead())==TOKEN_INT ||
        token_type(ahead())==TOKEN_VOID ||
        token_type(ahead())==TOKEN_STRUCT){
            if(token_type(ahead())==TOKEN_STRUCT){
                is_type = 0;
            }else if(token_type(ahead())==TOKEN_INT){
                is_type = 1;
            }else{
                is_type = 2;
            }
            parse_type_specifier();
            if(is_type == 0){
                ssym = matchedstack_pop();
                declist = matchedstack_pop();
                match(TOKEN_ID);
                sym = token_letter(matchedstack_pop());
                match(TOKEN_LEFT_BRACE);
                parse_parameters();
                arglist = matchedstack_pop();
                match(TOKEN_RIGHT_BRACE);
                parse_compound_statement();
                cstmt = matchedstack_pop();
                matchedstack_push(abt_function_dec(sym,ABT_DEC_STRUCT,arglist,cstmt,ssym,declist));
            }else if(is_type == 1){
                match(TOKEN_ID);
                sym = token_letter(matchedstack_pop());
                match(TOKEN_LEFT_BRACE);
                parse_parameters();
                arglist = matchedstack_pop();
                match(TOKEN_RIGHT_BRACE);
                parse_compound_statement();
                cstmt = matchedstack_pop();
                matchedstack_push(abt_function_dec(sym,ABT_DEC_INT,arglist,cstmt,NULL,NULL));
            }else{
                match(TOKEN_ID);
                sym = token_letter(matchedstack_pop());
                match(TOKEN_LEFT_BRACE);
                parse_parameters();
                arglist = matchedstack_pop();
                match(TOKEN_RIGHT_BRACE);
                parse_compound_statement();
                cstmt = matchedstack_pop();
                matchedstack_push(abt_function_dec(sym,ABT_DEC_VOID,arglist,cstmt,NULL,NULL));
            }
        }else{
            parser_error_info("syntax error detected at function declaration");
            log_error();
        }
}

void parse_parameters(){
    token tk1 = 0;
    if(token_type(ahead())==TOKEN_VOID){
        tk1 = advance();
        if(token_type(ahead())==TOKEN_ID){
            previewstack_push(ahead());
            previewstack_push(tk1);
            advance();
            parse_parameter_list();
        }else{
            previewstack_push(ahead());
            previewstack_push(tk1);
            advance();          
            match(TOKEN_VOID);
            matchedstack_push(NULL);
        }
    }else if(token_type(ahead())==TOKEN_INT||
        token_type(ahead())==TOKEN_STRUCT){
        parse_parameter_list();
    }else{
        parser_error_info("syntax error detected at parameters");
        log_error();
    }
}

void parse_parameter_list(){
    abt_dec dec = NULL;
    if(token_type(ahead())==TOKEN_INT || token_type(ahead())==TOKEN_VOID ||
        token_type(ahead())==TOKEN_STRUCT){
            parse_parameter();
            dec = matchedstack_pop();
            parse_parameter_list_();
            matchedstack_push(abt_dec_list(dec,matchedstack_pop()));
    }else{
        parser_error_info("syntax error detected at paramter list");
        log_error();
    }
}

void parse_parameter_list_(){
    abt_dec dec = NULL;
    if(token_type(ahead())==TOKEN_COMMA){
        match(TOKEN_COMMA);
        parse_parameter();
        dec = matchedstack_pop();
        parse_parameter_list_();
        matchedstack_push(abt_dec_list(dec,matchedstack_pop()));
    }else{
        matchedstack_push(NULL);
        return;
    }
}

void parse_parameter(){
    token tk1 = 0;
    token tk2 = 0;
    int is_type = 0;
    char * ssym = NULL;
    char * sym = NULL;
    abt_declist declist = NULL;
    if(token_type(ahead())==TOKEN_VOID||
        token_type(ahead())==TOKEN_INT||
            token_type(ahead())==TOKEN_STRUCT){
        if(token_type(ahead())==TOKEN_STRUCT){
            is_type = 0;
        }else if(token_type(ahead())==TOKEN_INT){
            is_type = 1;
        }else{
            is_type = 2;
        }
        tk1 = advance();
        if(token_type(ahead())==TOKEN_ID){
            tk2 = advance();
            if(token_type(ahead())==TOKEN_LEFT_SBRACE){
                //数组
                previewstack_push(ahead());
                previewstack_push(tk2);
                previewstack_push(tk1);
                advance();
                parse_type_specifier();
                if(is_type == 0){
                    ssym = matchedstack_pop();
                    declist = matchedstack_pop();
                    match(TOKEN_ID);
                    sym = token_letter(matchedstack_pop());
                    match(TOKEN_LEFT_SBRACE);
                    match(TOKEN_RIGHT_SBRACE);
                    matchedstack_push(abt_array_dec(sym,0,ABT_DEC_STRUCT,ssym,declist));
                }else if(is_type == 1){
                    match(TOKEN_ID);
                    sym = token_letter(matchedstack_pop());
                    match(TOKEN_LEFT_SBRACE);
                    match(TOKEN_RIGHT_SBRACE);
                    matchedstack_push(abt_array_dec(sym,0,ABT_DEC_INT,NULL,NULL));
                }else{
                    match(TOKEN_ID);
                    sym = token_letter(matchedstack_pop());
                    match(TOKEN_LEFT_SBRACE);
                    match(TOKEN_RIGHT_SBRACE);
                    matchedstack_push(abt_array_dec(sym,0,ABT_DEC_VOID,NULL,NULL));
                }
                
            }else{
                //普通变量
                previewstack_push(ahead());
                previewstack_push(tk2);
                previewstack_push(tk1);
                advance();
                parse_type_specifier();
                if(is_type == 0){
                    ssym = matchedstack_pop();
                    declist = matchedstack_pop();
                    match(TOKEN_ID);
                    sym = token_letter(matchedstack_pop());
                    matchedstack_push(abt_struct_dec(sym,ssym,declist));
                }else if(is_type == 1){
                    match(TOKEN_ID);
                    sym = token_letter(matchedstack_pop());
                    matchedstack_push(abt_int_dec(sym));
                }else{
                    match(TOKEN_VOID);
                    sym = token_letter(matchedstack_pop());
                    matchedstack_push(abt_int_dec(sym));
                }
            }
        }else{
            parser_error_info("syntax error detected at parameter");
            log_error();
        }
    }else{
        parser_error_info("syntax error detected at parameter");
        log_error();
    }
}

void parse_compound_statement(){
    match(TOKEN_LEFT_CBRACE);
    parse_local_declarations();
    parse_statement_list();
    match(TOKEN_RIGHT_CBRACE);
}

void parse_local_declarations(){
    if(token_type(ahead())==TOKEN_VOID||
        token_type(ahead())==TOKEN_INT||
        token_type(ahead())==TOKEN_STRUCT){
            parse_variable_declaration();
            parse_local_declarations();
    }else{
            return;
    }
}

void parse_statement_list(){
    abt_stmt stmt = NULL;
    if(token_type(ahead())==TOKEN_GOTO||
        token_type(ahead())==TOKEN_BREAK||
        token_type(ahead())==TOKEN_LEFT_CBRACE||
        token_type(ahead())==TOKEN_IF||
        token_type(ahead())==TOKEN_RETURN||
        token_type(ahead())==TOKEN_FOR||
        token_type(ahead())==TOKEN_WHILE||
        token_type(ahead())==TOKEN_SEMICOLON||
        token_type(ahead())==TOKEN_LEFT_BRACE||
        token_type(ahead())==TOKEN_ID||
        token_type(ahead())==TOKEN_NUM){
            parse_statement();
            stmt = matchedstack_pop();
            parse_statement_list();
            matchedstack_push(abt_stmt_list(stmt,matchedstack_pop()));
    }else{
        matchedstack_push(NULL);
        return;
    }
}

void parse_statement(){
    if(token_type(ahead())==TOKEN_LEFT_CBRACE){
        parse_compound_statement();
    }else if(token_type(ahead())==TOKEN_ID||
                token_type(ahead())==TOKEN_NUM||
                    token_type(ahead())==TOKEN_LEFT_BRACE||
                        token_type(ahead())==TOKEN_SEMICOLON){
        parse_expression_statement();
    }else if(token_type(ahead())==TOKEN_IF){
        parse_selection_statement();
    }else if(token_type(ahead())==TOKEN_WHILE||
                token_type(ahead())==TOKEN_FOR){
        parse_iteration_statement();
    }else if(token_type(ahead())==TOKEN_BREAK||
                token_type(ahead())==TOKEN_RETURN||
                    token_type(ahead())==TOKEN_GOTO){
        parse_jump_statement();
    }else{
        log_error();
    }
}

void parse_expression_statement(){
    parse_optional_expression();
    match(TOKEN_SEMICOLON);
    matchedstack_pop();
    matchedstack_push(abt_expression_stmt(matchedstack_pop()));
}

void parse_optional_expression(){
    if(token_type(ahead())==TOKEN_ID||
        token_type(ahead())==TOKEN_NUM||
        token_type(ahead())==TOKEN_LEFT_BRACE){
        parse_expression();
    }else{
        matchedstack_push(NULL);
        return;
    }
}

void parse_selection_statement(){
    abt_stmt tstmt = NULL;
    abt_stmt fstmt = NULL;
    abt_exp exp = NULL;
    match(TOKEN_IF);
    match(TOKEN_LEFT_BRACE);
    parse_expression();
    exp = matchedstack_pop();
    match(TOKEN_RIGHT_BRACE);
    parse_statement();
    tstmt = matchedstack_pop();
    if(token_type(ahead())==TOKEN_ELSE){
        match(TOKEN_ELSE);
        parse_statement();
        fstmt = matchedstack_pop();
        matchedstack_push(abt_selection_stmt(exp,tstmt,fstmt));
    }else{
        matchedstack_push(abt_selection_stmt(exp,tstmt,fstmt));
        return;
    }
}

void parse_iteration_statement(){
    abt_exp while_exp = NULL;
    abt_exp exp1 = NULL;
    abt_exp exp2 = NULL;
    abt_exp exp3 = NULL;
    if(token_type(ahead())==TOKEN_WHILE){
        match(TOKEN_WHILE);
        match(TOKEN_LEFT_BRACE);
        parse_expression();
        while_exp = matchedstack_pop();
        match(TOKEN_RIGHT_BRACE);
        parse_statement();
        matchedstack_push(abt_while_stmt(while_exp,matchedstack_pop()));
    }else if(token_type(ahead())==TOKEN_FOR){
        match(TOKEN_FOR);
        match(TOKEN_LEFT_BRACE);
        parse_optional_expression();
        exp1 = matchedstack_pop();
        match(TOKEN_SEMICOLON);
        parse_optional_expression();
        exp2 = matchedstack_pop();
        match(TOKEN_SEMICOLON);
        parse_optional_expression();
        exp3 = matchedstack_pop();
        match(TOKEN_RIGHT_BRACE);
        parse_statement();
        matchedstack_push(abt_for_stmt(exp1,exp2,exp3,matchedstack_pop()));
    }else{
        log_error();
    }
}

void parse_jump_statement(){
    if(token_type(ahead())==TOKEN_RETURN){
        match(TOKEN_RETURN);
        parse_optional_expression();
        match(TOKEN_SEMICOLON);
        matchedstack_pop();
        matchedstack_push(abt_return_stmt(matchedstack_pop()));
    }else if(token_type(ahead())==TOKEN_BREAK){
        match(TOKEN_BREAK);
        match(TOKEN_SEMICOLON);
        matchedstack_push(abt_break_stmt());
    }else if(token_type(ahead())==TOKEN_GOTO){
        match(TOKEN_GOTO);
        match(TOKEN_SEMICOLON);
        matchedstack_push(abt_goto_stmt());
    }else{
        log_error();
    }
}

void parse_expression(){
    token tk1 = 0;
    token tk2 = 0;
    token tk3 = 0;
    token tk4 = 0;
    int type = 0;
    if(token_type(ahead())==TOKEN_NUM||
        token_type(ahead())==TOKEN_LEFT_BRACE){
        parse_conditional_expression();
        return;
    }
    if(token_type(ahead())==TOKEN_ID){
        tk1 = advance();
        if(token_type(ahead())==TOKEN_ASSIGN){
            previewstack_push(ahead());
            previewstack_push(tk1);
            advance();
            parse_assignment_expression();
            return;
        }else if(token_type(ahead())==TOKEN_LEFT_SBRACE){
            tk2 = advance();
            tk3 = advance();
            tk4 = advance();
            if(token_type(ahead())==TOKEN_ASSIGN){
                previewstack_push(ahead());
                previewstack_push(tk4);
                previewstack_push(tk3);
                previewstack_push(tk2);
                previewstack_push(tk1);
                advance();
                parse_assignment_expression();
                return;
            }else{
                previewstack_push(ahead());
                previewstack_push(tk4);
                previewstack_push(tk3);
                previewstack_push(tk2);
                previewstack_push(tk1);
                advance();
                parse_conditional_expression();
                return;
            }
        }else if(token_type(ahead())==TOKEN_DOT){
             tk2 = advance();
             tk3 = advance();
             if(token_type(ahead())==TOKEN_ASSIGN){
                previewstack_push(ahead());
                previewstack_push(tk3);
                previewstack_push(tk2);
                previewstack_push(tk1);
                advance();
                parse_assignment_expression();
                return;
             }else{
                previewstack_push(ahead());
                previewstack_push(tk3);
                previewstack_push(tk2);
                previewstack_push(tk1);
                advance();
                parse_conditional_expression();
                return;
             }
        }else{
            previewstack_push(ahead());
            previewstack_push(tk1);
            advance();
            parse_conditional_expression();
            return;
        }
    }else{
        log_error();
    }
}

void parse_assignment_expression(){
    abt_var var = NULL;
    parse_variable();
    var = matchedstack_pop();
    match(TOKEN_ASSIGN);
    matchedstack_pop();
    parse_expression();
    matchedstack_push(abt_assgin_exp(var,matchedstack_pop()));
}

void parse_variable(){
    token tk1 = 0;
    char * var_sym = NULL;
    match(TOKEN_ID);
    var_sym = token_letter(matchedstack_pop());
    if(token_type(ahead())==TOKEN_LEFT_SBRACE){
        match(TOKEN_LEFT_SBRACE);
        parse_expression();
        match(TOKEN_RIGHT_SBRACE);
        matchedstack_pop();
        matchedstack_push(abt_array_var(var_sym,matchedstack_pop()));
        return;
    }else if(token_type(ahead())==TOKEN_DOT){
        match(TOKEN_DOT);
        match(TOKEN_ID);
        matchedstack_push(abt_field_var(var_sym,token_letter(matchedstack_pop())));
        return;
    }else{
        matchedstack_push(abt_base_var(var_sym));
        return;
    }
}

void parse_conditional_expression(){
    abt_oper op = NULL;
    abt_exp left = NULL;
    parse_additive_expression();
    if(token_type(ahead())==TOKEN_GREAT||
        token_type(ahead())==TOKEN_GREAT_EQUAL||
        token_type(ahead())==TOKEN_LESS||
        token_type(ahead())==TOKEN_LESS_EQUAL||
        token_type(ahead())==TOKEN_EQUAL||
        token_type(ahead())==TOKEN_NOT_EQUAL){
        left = matchedstack_pop();
        parse_relation_operator();
        op = matchedstack_pop();
        parse_additive_expression();
        matchedstack_push(abt_oper_exp(op,left,matchedstack_pop()));
        return;
    }else{
        return;
    }
}

void parse_relation_operator(){
    if(token_type(ahead())==TOKEN_GREAT){
        match(TOKEN_GREAT);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_GREAT));
    }else if(token_type(ahead())==TOKEN_GREAT_EQUAL){
        match(TOKEN_GREAT_EQUAL);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_GREAT_EQUAL));
    }else if(token_type(ahead())==TOKEN_LESS){
        match(TOKEN_LESS);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_LESS));
    }else if(token_type(ahead())==TOKEN_LESS_EQUAL){
        match(TOKEN_LESS_EQUAL);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_LESS_EQUAL));
    }else if(token_type(ahead())==TOKEN_EQUAL){
        match(TOKEN_EQUAL);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_EQUAL));
    }else if(token_type(ahead())==TOKEN_NOT_EQUAL){
        match(TOKEN_NOT_EQUAL);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_NOT_EQUAL));
    }else{
        log_error();
    }
}

void parse_additive_expression(){
    parse_multiplicative_expression();
    parse_additive_expression_();
}

void parse_additive_expression_(){
    abt_oper op = NULL;
    abt_exp left = NULL;
    if(token_type(ahead())==TOKEN_ADD||token_type(ahead())==TOKEN_MINUS){
        left = matchedstack_pop();
        parse_add_operator();
        op = matchedstack_pop();
        parse_multiplicative_expression();
        matchedstack_push(abt_oper_exp(op,left,matchedstack_pop()));
        parse_additive_expression_();
    }else{
        return;
    }
}

void parse_add_operator(){
    if(token_type(ahead())==TOKEN_ADD){
        match(TOKEN_ADD);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_ADD));
    }else if(token_type(ahead())==TOKEN_MINUS){
        match(TOKEN_MINUS);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_MINUS));
    }else{
        log_error();
    }
}

void parse_multiplicative_expression(){
    parse_primary_expression();
    parse_multiplicative_expression_();
}

void parse_multiplicative_expression_(){
    abt_oper op = NULL;
    abt_exp left = NULL;
    if(token_type(ahead())==TOKEN_STAR||token_type(ahead())==TOKEN_DIV){
        left = matchedstack_pop();
        parse_mul_operator();
        op = matchedstack_pop();
        parse_primary_expression();
        matchedstack_push(abt_oper_exp(op,left,matchedstack_pop()));
        parse_multiplicative_expression_();
    }else{
        return;
    }
}

void parse_mul_operator(){
    if(token_type(ahead())==TOKEN_STAR){
        match(TOKEN_STAR);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_STAR));
    }else if(token_type(ahead())==TOKEN_DIV){
        match(TOKEN_DIV);
        matchedstack_pop();
        matchedstack_push(abt_op(ABT_OPER_DIV));
    }else{
        log_error();
    }
}

void parse_primary_expression(){
    token tk1 = 0;
    if(token_type(ahead())==TOKEN_ID){
        tk1 = advance();
        if(token_type(ahead())==TOKEN_LEFT_BRACE){
            previewstack_push(ahead());
            previewstack_push(tk1);
            advance();
            parse_call_function();
        }else{
            previewstack_push(ahead());
            previewstack_push(tk1);
            advance();
            parse_variable();
        }
    }else if(token_type(ahead())==TOKEN_NUM){
        match(TOKEN_NUM);
        matchedstack_push(abt_num_const(token_digit(matchedstack_pop())));
    }else if(token_type(ahead())==TOKEN_LEFT_BRACE){
        match(TOKEN_LEFT_BRACE);
        parse_expression();
        match(TOKEN_RIGHT_BRACE);
        matchedstack_pop();
    }else{
        log_error();
    }
}

void parse_call_function(){
    abt_var var=NULL;
    parse_variable();
    var =  matchedstack_pop();
    match(TOKEN_LEFT_BRACE);
    parse_arguments();
    match(TOKEN_RIGHT_BRACE);
    matchedstack_pop();
    matchedstack_push(abt_call_exp(var,matchedstack_pop()));
}

void parse_arguments(){
    if(token_type(ahead())==TOKEN_ID||
        token_type(ahead())==TOKEN_LEFT_BRACE||
            token_type(ahead())==TOKEN_NUM){
        parse_argument_list();
    }else{
        return;
    }
}

void parse_argument_list(){
    abt_exp exp = NULL;
    parse_expression();
    exp = matchedstack_pop();
    parse_argument_list_();
    matchedstack_push(abt_exp_list(exp,matchedstack_pop()));
}

void parse_argument_list_(){
    abt_exp exp = NULL;
    if(token_type(ahead())==TOKEN_COMMA){
        match(TOKEN_COMMA);
        parse_expression();
        exp = matchedstack_pop();
        parse_argument_list_();
        matchedstack_push(abt_exp_list(exp,matchedstack_pop()));
    }else{
        matchedstack_push(NULL);
        return;
    }
}